package algorithm.sort.radixSort;

import java.util.Arrays;

public class Radix {
    public static void main(String[] args) {
        int[] arr = {19, 97, 9, 17, 1, 8, 27};
        radix(arr);
        System.out.println(Arrays.toString(arr));

    }

    /** 基数排序
     * 桶排序升级版
     *
     * @param arr
     */
    public static void radix(int[] arr) {
        //定义10个桶,每个桶的大小都能装满整个数组
        int[][] bucket = new int[10][arr.length];

        //每一次取数的时候arr的下表
        int index = 0;

        //base表示个位数值或者十位、百位、千位等
        int base = 0;

        //定义一个一位数组记录每个桶中有多少个数据，方便取出
        //因为每一轮存数据的时候是覆盖式的存，并没有真正的从桶中删除上一轮的数据
        //所以不能用bucket[k].length来确定个数
        int[] bucketCounts = new int[10];

        //找出最大的数，循环的次数与最大的数有关
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if (arr[i] > max)
                max = arr[i];
        }

        //算出最大的数有几位,这里运用字符串的函数，比较巧妙
        int maxLength = (max + "").length();

        //将数组中的数全部放入到桶中
        for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
            //每次循环都按照每一位的大小放入到相应的桶中
            for (int j = 0; j < arr.length; j++) {
                //取出该位对应的值
                base = arr[j] / n % 10;
                bucket[base][bucketCounts[base]] = arr[j];
                bucketCounts[base]++;
            }

            //取出数据放到arr数组中,循环桶的个数，每一轮把一个桶中的数全部放入数组中
            index = 0;
            for (int k = 0; k < bucket.length; k++) {
                if (bucketCounts[k] != 0) {
                    for (int j = 0; j < bucketCounts[k]; j++) {
                        arr[index++] = bucket[k][j];
                    }
                }
                //每次循环把数放到桶中之后就将bucketCounts重置！！！特别重要！！！！
                //否则下次取数就会出错q
                bucketCounts[k] = 0;
            }
        }
    }
}
